﻿using UnityEngine;
using UnityEngine.UI;

namespace ZXthex.Html
{
    public class UGUIHtml_Builder
    {

        public Font font
        {
            get;set;
        }
        public UGUIHtml_Builder(RenderHtmlDocument rdoc, RectTransform uiContainer)
        {
            BindDocument(rdoc);
            BindUIContainer(uiContainer);
            font = Resources.GetBuiltinResource<Font>("Arial.ttf");
        }

        RenderHtmlDocument rdoc;
        RectTransform rootContainer;

        public void BindDocument(RenderHtmlDocument rdoc)
        {
            this.rdoc = rdoc;
        }

        public void BindUIContainer(RectTransform uiContainer)
        {
            rootContainer = uiContainer;
        }

        public UGUI_HtmlDocument GenerateUGUI()
        {

            UGUI_HtmlNode body = Create(rdoc, rootContainer);

            UGUI_HtmlDocument udoc = new UGUI_HtmlDocument(body);

            return udoc;
        }

        UGUI_HtmlNode Create(RenderHtmlDocument rdoc, RectTransform uiContainer)
        {
            UGUI_HtmlNodeBrush brush = new UGUI_HtmlNodeBrush();
            return CreateNode(rdoc.Body, uiContainer, ref brush);
        }


        
        UGUI_HtmlNode CreateNode(RenderHtmlNode node, RectTransform uiContainer, ref UGUI_HtmlNodeBrush brush)
        {
            string name = node.Name;
            if (!string.IsNullOrEmpty(node.Id))
            {
                name += " [id: " + node.Id + "]";
            }
            if ((node.GetAttribute("class") != null))
            {

                name += "[class: " + node.GetAttribute("class").Value + "]";
            }
            GameObject g = new GameObject(name, typeof(RectTransform));
            var rt = g.transform as RectTransform;

            rt.SetParent(uiContainer);
            rt.localScale = Vector3.one;

            rt.anchorMin = new Vector2(0, 0);
            rt.anchorMax = new Vector2(1, 1);
            rt.pivot = new Vector2(0, 1);
            rt.anchoredPosition = brush.offset_pos;
            rt.sizeDelta = new Vector2();

            RectTransform self = new GameObject("self", typeof(RectTransform)).transform as RectTransform;
            self.SetParent(rt);
            UGUI_Utility.SetFullSize(self);

            Image bg = new GameObject("background", typeof(RectTransform)).AddComponent<Image>();
            Text innerText = new GameObject("innerText", typeof(RectTransform)).AddComponent<Text>();
            RectTransform front = new GameObject("front", typeof(RectTransform)).transform as RectTransform;

            innerText.font = font;
            innerText.color = Color.black;

            bg.transform.SetParent(self);
            bg.color = Color.clear;
            UGUI_Utility.SetFullSize(bg.rectTransform);

            innerText.transform.SetParent(self);
            UGUI_Utility.SetFullSize(innerText.rectTransform);

            front.SetParent(self);
            UGUI_Utility.SetFullSize(front);

            var outlines = new UGUI_HtmlNodeOutline(front);
            

            if (!string.IsNullOrEmpty(node.InnerText))
            {
                innerText.text = node.InnerText;

                brush.offset_pos += innerText.fontSize * 1.2f * Vector2.down;
            }


            bool lock_height = false;
            bool abs_pos = false;

            for (int i = 0; i < node.Declarations.Length; i++)
            {

                if (node.Declarations[i].name == "position")
                {
                    if (node.Declarations[i].values[0] == "absolute")
                    {
                        abs_pos = true;
                        rt.anchoredPosition = Vector2.zero;
                    }
                }
            }


            for (int i = 0; i < node.Declarations.Length; i++)
            {

                if (node.Declarations[i].name == "width")
                {
                    if (node.Declarations[i].values[0].Contains("px"))
                    {
                        int widthpx = int.Parse(node.Declarations[i].values[0].Replace("px", ""));
                        float totalpx = uiContainer.rect.width;
                        var size = rt.sizeDelta;
                        size.x = widthpx - totalpx;
                        rt.sizeDelta = size;
                    }
                    else if (node.Declarations[i].values[0].Contains("%"))
                    {
                        int widthpc = int.Parse(node.Declarations[i].values[0].Replace("%", ""));
                        float totalpx = uiContainer.rect.width;
                        var size = rt.sizeDelta;
                        size.x = totalpx * (0.01f * widthpc - 1);
                        rt.sizeDelta = size;
                    }
                }
                else if (node.Declarations[i].name == "height")
                {
                    lock_height = true;
                    if (!string.IsNullOrEmpty(node.InnerText))
                    {
                        brush.offset_pos -= innerText.fontSize * 1.2f * Vector2.down;
                    }



                    if (node.Declarations[i].values[0].Contains("px"))
                    {
                        int heightpx = int.Parse(node.Declarations[i].values[0].Replace("px", ""));
                        float totalpx = uiContainer.rect.height;
                        var size = rt.sizeDelta;
                        size.y = heightpx - totalpx;
                        rt.sizeDelta = size;
                        brush.offset_pos += Vector2.down * heightpx;
                    }
                    else if (node.Declarations[i].values[0].Contains("%"))
                    {
                        int heightpc = int.Parse(node.Declarations[i].values[0].Replace("%", ""));
                        float totalpx = uiContainer.rect.height;
                        var size = rt.sizeDelta;
                        size.y = heightpc * 0.01f * totalpx - totalpx;
                        rt.sizeDelta = size;
                        brush.offset_pos += Vector2.down * heightpc * 0.01f * totalpx;
                    }
                }
                else if (node.Declarations[i].name == "color")
                {
                    Color c;
                    if (CSSColor.TryParse(node.Declarations[i].values[0], out c))
                    {
                        innerText.color = c;
                    }
                }
                else if (node.Declarations[i].name == "background"
                    || node.Declarations[i].name == "background-color")
                {
                    Color c;
                    if (CSSColor.TryParse(node.Declarations[i].values[0], out c))
                    {
                        bg.color = c;
                    }
                }
                else if (node.Declarations[i].name == "margin-left")
                {
                    if (node.Declarations[i].values[0].Contains("px"))
                    {
                        int widthpx = int.Parse(node.Declarations[i].values[0].Replace("px", ""));
                        float totalpx = uiContainer.rect.width;
                        rt.anchoredPosition = (abs_pos ? Vector2.zero : brush.offset_pos) + widthpx * Vector2.right;
                    }
                    else if (node.Declarations[i].values[0].Contains("%"))
                    {
                        int widthpc = int.Parse(node.Declarations[i].values[0].Replace("%", ""));
                        float totalpx = uiContainer.rect.width;
                        rt.anchoredPosition = (abs_pos ? Vector2.zero : brush.offset_pos) + widthpc * totalpx * 0.01f * Vector2.right;
                    }
                }
                else if (node.Declarations[i].name == "border")
                {
                    for (int j = 0; j < node.Declarations[i].values.Length; j++)
                    {
                        if (node.Declarations[i].values[j].Contains("px"))
                        {
                            outlines.SetOutlineWidth(int.Parse(node.Declarations[i].values[j].Replace("px", "")));
                        }
                        else if (node.Declarations[i].values[j] == "solid")
                        {
                            outlines.SetColor(Color.black);
                        }
                    }
                }
            }

            if (node.Name.ToLower() == "table")
            {
                Vector2 offset = new Vector2();
                CreateTableNode(node, rt, ref offset);
                if (!lock_height)
                {
                    brush.offset_pos += offset;
                }
            }
            else if (node.Name.ToLower() == "tr")
            {

            }
            else if (node.Name.ToLower() == "select")
            {

            }
            else if (node.Name.ToLower() == "h1"
                    || node.Name.ToLower() == "h2"
                    || node.Name.ToLower() == "h3"
                    || node.Name.ToLower() == "h4"
                    || node.Name.ToLower() == "h5")
            {

                innerText.fontSize += ('4' - node.Name[1]) * 2;
                innerText.fontStyle = FontStyle.Bold;
                var h = innerText.preferredHeight + 6;
                var rts = new RectTransform[] { innerText.rectTransform, self, rt };
                Debug.Log(rt.name);
                for (int i = 0; i < rts.Length; i++)
                {
                    rts[i].anchorMin = new Vector2(0, 1);
                    rts[i].sizeDelta = new Vector2(0, h);
                    rts[i].pivot = new Vector2(0.5f, 1);
                }
                brush.offset_pos += Vector2.down * h;
            }
            else if (node.Name.ToLower() == "p")
            {
                var h = innerText.preferredHeight + 6;
                var rts = new RectTransform[] { innerText.rectTransform, self, rt };
                Debug.Log(rt.name);
                for (int i = 0; i < rts.Length; i++)
                {
                    rts[i].anchorMin = new Vector2(0, 1);
                    rts[i].sizeDelta = new Vector2(0, h);
                    rts[i].pivot = new Vector2(0.5f, 1);
                }
                brush.offset_pos += Vector2.down * h;
            }
            else if (node.Name.ToLower() == "br")
            {
                var h = 16 + 6;
                var rts = new RectTransform[] { innerText.rectTransform, self, rt };
                Debug.Log(rt.name);
                for (int i = 0; i < rts.Length; i++)
                {
                    rts[i].anchorMin = new Vector2(0, 1);
                    rts[i].sizeDelta = new Vector2(0, h);
                    rts[i].pivot = new Vector2(0.5f, 1);
                }
                brush.offset_pos += Vector2.down * h;
            }
            else
            {
                UGUI_HtmlNodeBrush sub = new UGUI_HtmlNodeBrush();
                for (int i = 0; i < node.ChildCount; i++)
                {
                    if (node.Name.ToLower() == "table")
                    {
                        Debug.Log("offset: " + sub.offset_pos);
                    }
                    CreateNode(node.GetChild(i), rt, ref sub);
                }
                if (!lock_height)
                {
                    brush.offset_pos += sub.offset_pos;
                }
            }

            return new UGUI_HtmlNode(node, rt);
        }

        void CreateTableNode(RenderHtmlNode table, RectTransform uiContainer, ref Vector2 offset_pos)
        {

                UGUI_HtmlNodeBrush sub = new UGUI_HtmlNodeBrush();
                for (int i = 0; i < table.ChildCount; i++)
                { 
                    CreateNode(table.GetChild(i), uiContainer, ref sub);
                }
                //if (!lock_height)
                //{
                //    brush.offset_pos += sub.offset_pos;
                //}
            
        }

        void CreateTableRowNode(RenderHtmlNode tr, RectTransform uiContainer, ref Vector2 offset_pos)
        {

        }

        void CreateTableHeaderNode(RenderHtmlNode th, RectTransform uiContainer, ref Vector2 offset_pos)
        {

        }

        void CreateTableCellNode(RenderHtmlNode td, RectTransform uiContainer, ref Vector2 offset_pos)
        {

        }
    }
}